package com.autumn.zero.workflow.application.services.impl;

import java.util.HashSet;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.autumn.common.api.application.dto.input.IStatusInput;
import com.autumn.common.api.constants.BasiscArchivesStatusConstant;
import com.autumn.mybatis.criterion.EntityQuery;
import com.autumn.util.DataRollbackException;
import com.autumn.util.ExceptionUtils;
import com.autumn.zero.application.services.AbstractZeroEditAppService;
import com.autumn.zero.workflow.application.dto.forms.WorkflowFormDetailsOutput;
import com.autumn.zero.workflow.application.dto.forms.WorkflowFormInput;
import com.autumn.zero.workflow.application.dto.forms.WorkflowFormOutput;
import com.autumn.zero.workflow.application.services.IWorkflowFormAppService;
import com.autumn.zero.workflow.entitys.WorkflowDefinition;
import com.autumn.zero.workflow.entitys.WorkflowForm;
import com.autumn.zero.workflow.entitys.WorkflowFormProperty;
import com.autumn.zero.workflow.repositorys.IWorkflowDefinitionRepository;
import com.autumn.zero.workflow.repositorys.IWorkflowFormPropertyRepository;
import com.autumn.zero.workflow.repositorys.IWorkflowFormRepository;

/**
 * 默认工作流表单应用服务
 * 
 * @author 老码农 2018-12-20 00:18:23
 */
public class WorkflowFormAppServiceImpl extends
		AbstractZeroEditAppService<Long, WorkflowForm, IWorkflowFormRepository, WorkflowFormInput, WorkflowFormInput, WorkflowFormDetailsOutput, WorkflowForm, IWorkflowFormRepository, WorkflowFormOutput>
		implements IWorkflowFormAppService {

	@Autowired
	private IWorkflowFormRepository repository;

	@Autowired
	private IWorkflowFormPropertyRepository propertyRepository;

	@Autowired
	private IWorkflowDefinitionRepository workflowDefinitionRepository;

	@Override
	public String getModuleName() {
		return "工作流表单";
	}

	@Override
	protected IWorkflowFormRepository getRepository() {
		return this.repository;
	}

	@Override
	protected IWorkflowFormRepository getQueryRepository() {
		return this.getRepository();
	}

	private Set<String> searchMembers = new HashSet<>();

	@Override
	protected Set<String> getSearchMembers() {
		if (searchMembers.size() == 0) {
			searchMembers.add(WorkflowForm.FILED_FORM_NAME);
		}
		return searchMembers;
	}

	@Override
	protected void queryByOrder(EntityQuery<WorkflowForm> query) {
		query.orderBy(WorkflowForm.FILED_FORM_TYPE).orderBy("id");
	}

	private void editCheck(WorkflowFormInput input, EntityQuery<WorkflowForm> query, boolean checkType,
			boolean checkName) {
		if (checkType) {
			query.reset();
			query.eq(WorkflowForm.FILED_FORM_TYPE, input.getFormType());
			if (query.exist(this.repository)) {
				ExceptionUtils.throwValidationException(String.format("表单类型[%s]已经重复。", input.getFormType()));
			}
		}
		if (checkName) {
			query.reset();
			query.eq(WorkflowForm.FILED_FORM_NAME, input.getFormName());
			if (query.exist(this.repository)) {
				ExceptionUtils.throwValidationException(String.format("表单名称[%s]已经重复。", input.getFormType()));
			}
		}
	}

	/**
	 * 添加属性集合
	 * 
	 * @param entity 实体
	 */
	private void addPropertys(WorkflowForm entity) {
		if (entity.getPropertys() != null) {
			for (WorkflowFormProperty item : entity.getPropertys()) {
				item.setFormId(entity.getId());
				propertyRepository.insert(item);
			}
		}
	}

	/**
	 * 删除属性集合
	 * 
	 * @param id 主键
	 */
	private void deletePropertys(Long id) {
		EntityQuery<WorkflowFormProperty> query = new EntityQuery<>(WorkflowFormProperty.class);
		query.eq(WorkflowFormProperty.FILED_FORM_ID, id);
		query.deleteByWhere(this.propertyRepository);
	}

	@Override
	protected WorkflowForm addBefore(WorkflowFormInput input, EntityQuery<WorkflowForm> query) {
		this.editCheck(input, query, true, true);
		WorkflowForm result = super.addBefore(input, query);
		result.setStatus(BasiscArchivesStatusConstant.ENABLE);
		return result;
	}

	@Override
	protected WorkflowFormDetailsOutput addAfter(WorkflowFormInput input, WorkflowForm entity,
			EntityQuery<WorkflowForm> query) {
		this.addPropertys(entity);
		return super.addAfter(input, entity, query);
	}

	private boolean isQuoteFormType(int formType) {
		EntityQuery<WorkflowDefinition> query = new EntityQuery<>(WorkflowDefinition.class);
		query.eq(WorkflowDefinition.FILED_FORM_TYPE, formType);
		return query.exist(this.workflowDefinitionRepository);
	}

	@Override
	protected void updateBefore(WorkflowFormInput input, WorkflowForm entity, EntityQuery<WorkflowForm> query) {
		this.editCheck(input, query, !entity.getFormType().equals(input.getFormType()),
				!entity.getFormName().trim().equalsIgnoreCase(input.getFormName().trim()));
		if (!entity.getFormType().equals(input.getFormType())) {
			if (this.isQuoteFormType(entity.getFormType())) {
				ExceptionUtils.throwValidationException("指定的表单类型已被引用，不能修改。");
			}
		}
		super.updateBefore(input, entity, query);
	}

	@Override
	protected WorkflowFormDetailsOutput updateAfter(WorkflowFormInput input, WorkflowForm entity,
			WorkflowForm oldEntity, EntityQuery<WorkflowForm> query) {
		this.deletePropertys(entity.getId());
		this.addPropertys(entity);
		return super.updateAfter(input, entity, oldEntity, query);
	}

	@Override
	protected void deleteBefore(Long id) {
		WorkflowForm entity = super.getEntity(id);
		if (entity != null) {
			if (this.isQuoteFormType(entity.getFormType())) {
				ExceptionUtils.throwValidationException("指定的表单类型已被引用，不能删除。");
			}
			this.deletePropertys(id);
		}
		super.deleteBefore(id);
	}

	@Override
	protected WorkflowForm getEntity(Long id) {
		WorkflowForm entity = super.getEntity(id);
		if (entity != null) {
			EntityQuery<WorkflowFormProperty> query = new EntityQuery<>(WorkflowFormProperty.class);
			query.eq(WorkflowFormProperty.FILED_FORM_ID, id).orderBy(WorkflowFormProperty.FILED_ID);
			entity.setPropertys(query.selectByList(this.propertyRepository));
		}
		return entity;
	}

	/**
	 * 
	 */
	@Override
	@Transactional(rollbackFor = DataRollbackException.class)
	public void updateByStatus(IStatusInput<Long> input) {
		ExceptionUtils.checkNotNull(input, "input");
		ExceptionUtils.checkNotNull(input.getId(), "id");
		ExceptionUtils.checkNotNull(input.getStatus(), "status");
		if (!BasiscArchivesStatusConstant.exist(input.getStatus())) {
			ExceptionUtils.throwValidationException(this.getModuleName() + "无效或不支持。");
		}
		WorkflowForm entity = super.getEntity(input.getId());
		if (entity == null) {
			ExceptionUtils.throwValidationException("无法更新不存在" + this.getModuleName() + "状态。");
		}
		entity.setStatus(input.getStatus());
		this.updateAuditing(entity);
		this.getRepository().update(entity);
	}

}
